package Logica.Util.implementacion;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import Logica.Util.contrato.IFecha;
import Logica.Util.contrato.IFechaModel;
import Logica.excepciones.IllegalDateFormatException;
import Logica.miscelanea.contrato.Calendario;

public class Fecha implements IFecha, IFechaModel, Serializable {

	private static final long serialVersionUID = -1660164815034028995L;

	private Calendar calendario;
	private String patronFecha = "dd/MM/yyyy";
	SimpleDateFormat formatter = new SimpleDateFormat(patronFecha);

	public Fecha() {
		this.calendario = formatter.getCalendar();
	}
	
	public Fecha(Date fechaDate){
		this.calendario = Calendar.getInstance();
		this.calendario.setTime(fechaDate);
	}

	public Fecha(int dia, int mes, int anyo) {
		this.setDia(dia);
		this.setMes(mes);
		this.setAnyo(anyo);
	}

	public Fecha(String fecha) {
		if (fecha == null)
			throw new NullPointerException();

		if (fecha == " " || fecha == "")
			throw new IllegalArgumentException(
					"La cadena para crear una fecha no puede ser vacia o solo un espacio");
		inicializaParametros(fecha);

	}

	private void inicializaParametros(String fecha) {
		Date fechaDate;
		try {
			fechaDate = formatter.parse(fecha);
			this.calendario.setTime(fechaDate);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		int dia, mes, anyo;
		dia = calendario.get(calendario.DATE);
		mes = calendario.get(calendario.MONTH) + 1;
		anyo = calendario.get(calendario.YEAR);
		try {
			String fechaString = dia + "/" + mes + "/" + anyo;
			this.formatter.parse(fechaString);
			this.calendario = formatter.getCalendar();
		} catch (ParseException e) {
			System.out
					.println("Error para crear la fecha con el formato de la cadena. No ha podido ser creada con los parámetros: \nDia: "
							+ dia + "  Mes: " + mes + "  Anyo: " + anyo);
			e.printStackTrace();
		}
	}

	private void actualizaFecha(int type, int value) {
		int dia, mes, anyo;
		dia = calendario.get(Calendar.DATE);
		mes = calendario.get(Calendar.MONTH);
		anyo = calendario.get(Calendar.YEAR);
		switch (type) {
		case Calendar.DATE:
			dia = value;
			break;
		case Calendar.MONTH:
			mes = value;
			break;
		case Calendar.YEAR:
			anyo = value;
		default:
			break;
		}

	}

	public void setMes(int mes) {
		if (mes < 1 || mes > 12)
			throw new IllegalArgumentException(
					"Valor para parámetro mes incorrecto: " + mes);
		actualizaFecha(Calendar.MONTH, mes);
	}

	public void setDia(int dia) {
		if (dia < 1 || dia > 31)
			throw new IllegalArgumentException(
					"Valor para parámetro dia incorrecto: " + dia);
		actualizaFecha(Calendar.DATE, dia);
	}

	public void setAnyo(int anyo) {
		if (anyo <= 0)
			throw new IllegalArgumentException(
					"Valor para parámetro año incorrecto: " + anyo);
		actualizaFecha(Calendar.YEAR, anyo);
	}

	public int getDia() {
		return this.calendario.get(Calendar.DATE);
	}

	public int getMes() {
		return this.calendario.get(Calendar.MONTH);
	}

	public int getAnyo() {
		return this.calendario.get(Calendar.YEAR);
	}

	public String getPatronFecha() {
		return patronFecha;
	}

	public void setPatronFecha(String patronFecha) {
		if (patronFecha == null)
			throw new NullPointerException(
					"El argumento patronFecha no puede ser null");
		if (patronFecha == "" || patronFecha == " ")
			throw new IllegalArgumentException(
					"El argumento patronFecha no es correcto: " + patronFecha);
		this.patronFecha = patronFecha;
	}

	public boolean anterior(IFecha fecha) {
		boolean result = false;
		if (fecha.getAnyo() > this.getAnyo() || fecha.getMes() > this.getMes()
				|| fecha.getDia() > this.getDia())
			result = true;
		return result;
	}

	public boolean equal(Object obj) {
		if (obj == null)
			return false;
		if (this == obj)
			return true;
		if (getClass() != obj.getClass())
			return false;

		IFecha other = (IFecha) obj;
		boolean result = true;

		if (this.getAnyo() != other.getAnyo()
				|| this.getMes() != other.getMes()
				|| this.getDia() != other.getDia())
			result = false;
		return result;
	}

	public int compare(IFecha fecha) {
		int result;
		if (this.equal(fecha))
			result = 0;
		else if (this.anterior(fecha))
			result = -1;
		else
			result = 1;
		return result;
	}

	public static Fecha getFechaActual() {
		Calendar calendarioHoy = Calendar.getInstance();
		Fecha hoy = new Fecha(calendarioHoy.get(Calendar.DATE),
				calendarioHoy.get(Calendar.MONTH),
				calendarioHoy.get(Calendar.YEAR));
		return hoy;
	}

	public boolean esAnterior(IFecha fecha) {
		boolean result = false;
		
		Date fechaArgumento = fecha.getDate();
				
		// TODO: comprobar si la comparación con date
		// 		 funciona bien en una entrega que se haga
		//		 la fecha límite del trabajo
		
//		if( fecha.getAnyo() < this.getAnyo() ){
//			result = true;
//		}
//		else{
//			if(fecha.getMes() < this.getMes())
//				result = true;
//			else{
//				if( fecha.getDia() < this.getDia() )
//					result = true;
//			}
//		}
		
		result = this.calendario.before(fechaArgumento);
		return result;
	}

	public Date getDate() {
		return this.calendario.getTime();
	}


}

